package cn.edu.pzhu.javaweb.util;

import javax.sql.DataSource;

import org.junit.jupiter.api.Test;

import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

/**
 * Druid数据库连接池工具类
 * 使用标准Java API中的DataSource接口
 * getConnection()方法内部处理异常，不抛出
 */
public class DruidUtil {
    
    private static DataSource dataSource;
    
    // 静态代码块，在类加载时初始化连接池
    static {
        initDataSource();
    }
    
    /**
     * 初始化Druid连接池
     */
    private static void initDataSource() {
        try {
            // 加载properties配置文件
            Properties props = new Properties();
            InputStream is = DruidUtil.class.getClassLoader().getResourceAsStream("druid.properties");
            
            if (is == null) {
                System.err.println("错误：找不到druid.properties配置文件");
                return;
            }
            
            // 加载配置文件
            props.load(is);
            is.close();
            
            // 使用反射创建DruidDataSource实例并配置
            Class<?> druidDataSourceClass = Class.forName("com.alibaba.druid.pool.DruidDataSource");
            dataSource = (DataSource) druidDataSourceClass.newInstance();
            
            // 设置连接池属性
            setProperty(dataSource, "driverClassName", props.getProperty("driverClassName"));
            setProperty(dataSource, "url", props.getProperty("url"));
            setProperty(dataSource, "username", props.getProperty("username"));
            setProperty(dataSource, "password", props.getProperty("password"));
            setProperty(dataSource, "initialSize", props.getProperty("initialSize"));
            setProperty(dataSource, "maxActive", props.getProperty("maxActive"));
            setProperty(dataSource, "maxWait", props.getProperty("maxWait"));
            
            System.out.println("Druid连接池初始化成功！");
            
        } catch (Exception e) {
            System.err.println("Druid连接池初始化失败！");
            e.printStackTrace();
        }
    }
    
    /**
     * 使用反射设置属性
     */
    private static void setProperty(Object obj, String propertyName, String propertyValue) {
        if (propertyValue == null) return;
        
        try {
            String setterName = "set" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
            Class<?> paramType = getPropertyType(propertyName);
            
            if (paramType == int.class || paramType == Integer.class) {
                obj.getClass().getMethod(setterName, paramType).invoke(obj, Integer.parseInt(propertyValue));
            } else if (paramType == long.class || paramType == Long.class) {
                obj.getClass().getMethod(setterName, paramType).invoke(obj, Long.parseLong(propertyValue));
            } else {
                obj.getClass().getMethod(setterName, paramType).invoke(obj, propertyValue);
            }
        } catch (Exception e) {
            System.err.println("设置属性 " + propertyName + " 失败: " + e.getMessage());
        }
    }
    
    /**
     * 根据属性名获取属性类型
     */
    private static Class<?> getPropertyType(String propertyName) {
        switch (propertyName) {
            case "initialSize":
            case "maxActive":
                return int.class;
            case "maxWait":
                return long.class;
            default:
                return String.class;
        }
    }
    
    /**
     * 获取数据源实例
     * @return DataSource 数据源对象，如果初始化失败则返回null
     */
    public static DataSource getDataSource() {
        return dataSource;
    }
    
    /**
     * 从连接池获取数据库连接
     * 注意：此方法不抛出异常，发生异常时返回null并打印异常栈
     * @return Connection 数据库连接，如果获取失败则返回null
     */
    public static Connection getConnection() {
        if (dataSource == null) {
            System.err.println("错误：数据源未初始化，无法获取连接");
            return null;
        }
        
        try {
            Connection connection = dataSource.getConnection();
            return connection;
        } catch (SQLException e) {
            System.err.println("获取数据库连接时发生异常：");
            e.printStackTrace();
            return null;
        }
    }
    
    /**
     * 安全地关闭连接
     * @param conn 要关闭的连接
     */
    public static void closeConnection(Connection conn) {
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                System.err.println("关闭数据库连接时发生错误：");
                e.printStackTrace();
            }
        }
    }
    
    /**
     * 关闭连接池（在应用关闭时调用）
     */
    public static void closeDataSource() {
        if (dataSource != null) {
            try {
                // 使用反射调用close方法
                dataSource.getClass().getMethod("close").invoke(dataSource);
                System.out.println("Druid连接池已关闭！");
            } catch (Exception e) {
                System.err.println("关闭Druid连接池时发生错误：");
                e.printStackTrace();
            }
        }
    }
    
    /**
     * 测试连接池功能
     */
    public static void testConnectionPool() {
        System.out.println("开始测试Druid连接池...");
        
        // 测试获取多个连接
        for (int i = 1; i <= 5; i++) {
            Connection con = getConnection();
            if (con != null) {
                System.out.println("第" + i + "次获取连接成功: " + con);
                // 不立即关闭，测试连接池行为
                if (i == 3) {
                    closeConnection(con);
                    System.out.println("第3次连接已关闭");
                }
            } else {
                System.out.println("第" + i + "次获取连接失败");
            }
        }
        
        // 测试连接池状态
        printPoolStatus();
    }
    
    /**
     * 打印连接池状态信息
     */
    public static void printPoolStatus() {
        if (dataSource == null) {
            System.out.println("连接池未初始化");
            return;
        }
        
        try {
            // 使用反射获取连接池状态
            int activeCount = (int) dataSource.getClass().getMethod("getActiveCount").invoke(dataSource);
            int poolingCount = (int) dataSource.getClass().getMethod("getPoolingCount").invoke(dataSource);
            
            System.out.println("=== Druid连接池状态 ===");
            System.out.println("活跃连接数: " + activeCount);
            System.out.println("池中空闲连接数: " + poolingCount);
            System.out.println("=======================");
        } catch (Exception e) {
            System.err.println("获取连接池状态时发生错误：");
            e.printStackTrace();
        }
    }
    
    @Test
    public void test() throws SQLException {
        // 测试连接池
        for (int i = 1; i <= 11; i++) {
            Connection con = DruidUtil.getConnection();
            System.out.println("第" + i + "次获取连接: " + con);
            if (i == 5) {
                DruidUtil.closeConnection(con);
                System.out.println("第5次连接已关闭");
            }
        }
        // 打印连接池状态
        DruidUtil.printPoolStatus();
    }
    /**
     * 主方法 - 测试用
     */
    public static void main(String[] args) {
        // 运行连接池测试
        testConnectionPool();
        
        // 关闭连接池
        closeDataSource();
    }
}